/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nacestrutura;

import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;

import java.io.IOException;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JPanel;

import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.io.GraphMLWriter;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.picking.PickedState;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Collection;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import org.apache.commons.collections15.Factory;

/**
 * Demonsrates TreeLayout and RadialTreeLayout.
 *
 * @author Tom Nelson
 *
 */
@SuppressWarnings("serial")
public class Grafo extends JApplet {

    Graph<String, edge> graph;
    VisualizationViewer<String, edge> visualizationViewer;
    AbstractLayout<String, edge> layout;
    public String verticeSelecionado = "";
    public edge arestaSelecionada = null;
    private final static int COMBO_OPTION_VALUE = 3;
    int intEdgeId = 0;

    public Grafo() {

        graph = new DirectedSparseMultigraph<String, edge>();
        
        this.layout = new StaticLayout<String, edge>(graph, new Dimension(600, 600));
        visualizationViewer = new VisualizationViewer<String, edge>(layout, new Dimension(600, 600));
        visualizationViewer.setBackground(Color.white);
        visualizationViewer.getRenderContext().setEdgeShapeTransformer(new EdgeShape.QuadCurve());
        visualizationViewer.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
        visualizationViewer.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller());

        Container content = getContentPane();
        final GraphZoomScrollPane panel = new GraphZoomScrollPane(visualizationViewer);
        content.add(panel);
        Factory<String> vertexFactory = new Grafo.VertexFactory();
        Factory<edge> edgeFactory = new Grafo.EdgeFactory(intEdgeId++);

        final EditingModalGraphMouse<String, edge> graphMouse =
                new EditingModalGraphMouse<String, edge>(visualizationViewer.getRenderContext(), vertexFactory, edgeFactory);

        // the EditingGraphMouse will pass mouse event coordinates to the
        // vertexLocations function to set the locations of the vertices as
        // they are created
        //        graphMouse.setVertexLocations(vertexLocations);
        visualizationViewer.setGraphMouse(graphMouse);
        visualizationViewer.addKeyListener(graphMouse.getModeKeyListener());

        graphMouse.setMode(ModalGraphMouse.Mode.EDITING);

        final ScalingControl scaler = new CrossoverScalingControl();

        JButton btnRemoverNo = new JButton("Remover");
        
        btnRemoverNo.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                scaler.scale(visualizationViewer, 1 / 1.1f, visualizationViewer.getCenter());

                if (!verticeSelecionado.isEmpty()) {
                    graph.removeVertex(verticeSelecionado);
                } else if (arestaSelecionada != null) {
                    graph.removeEdge(arestaSelecionada);
                }
                layout.setGraph(graph);
                visualizationViewer.repaint();
            }
        });

        JButton btnExportarGrafo = new JButton("Exportar");
        btnExportarGrafo.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                scaler.scale(visualizationViewer, 1 / 1.1f, visualizationViewer.getCenter());

                if (graph.containsVertex("Inicio")) {
                    if (verticeSelecionado.isEmpty()) {
                        JOptionPane.showMessageDialog(null, "Selecione o vértice principal", "Exportação", 2);
                    } else {
                        ExportarXML();
                        JOptionPane.showMessageDialog(null, "Grafo exportado com sucesso");
                    }
                } else {
                    JOptionPane.showMessageDialog(null, "É necessário ter um nó inicial para exportar o grafo");
                }
            }
        });

        // Attach the listener for listening to when vertices are selected (or deselected).
        // You can also listen for changes to the selection of edges, by using visualizationViewer.getPickedEdgeState() in
        // place of visualizationViewer.getPickedVertexState().
        // vertice(no)
        final PickedState<String> pickedStateVertex = visualizationViewer.getPickedVertexState();
        pickedStateVertex.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                Object subject = e.getItem();
                if (subject instanceof String) {
                    String vertex = (String) subject;
                    if (pickedStateVertex.isPicked(vertex)) {
                        verticeSelecionado = vertex;
                    } else {
                        verticeSelecionado = "";
                    }
                }
            }
        });

        //aresta
        final PickedState<edge> pickedStateEdge = visualizationViewer.getPickedEdgeState();
        pickedStateEdge.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                Object subject = e.getItem();
                if (subject instanceof String) {
                    edge ed = (edge) subject;
                    if (pickedStateEdge.isPicked(ed)) {
                        arestaSelecionada = ed;
                    } else {
                        arestaSelecionada = null;
                    }
                }
            }
        });

        JComboBox modeBox = graphMouse.getModeComboBox();
        modeBox.removeItemAt(COMBO_OPTION_VALUE);
        modeBox.addItemListener(graphMouse.getModeListener());

        JPanel controls = new JPanel();

        controls.add(btnExportarGrafo);
        controls.add(modeBox);
        controls.add(btnRemoverNo);
        content.add(controls, BorderLayout.SOUTH);
    }

    /**
     *
     */
    public void CriarGrafo() {
        JFrame frame = new JFrame();

        Container content = frame.getContentPane();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        content.add(new Grafo());
        frame.pack();
        frame.setVisible(true);
    }

    public void ExportarXML() {
        GraphMLWriter graphMLW = new GraphMLWriter();
        try {
            JFileChooser jfcSalvar = new JFileChooser();
            
            if (jfcSalvar.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
                Writer writer = new FileWriter(jfcSalvar.getSelectedFile().getAbsolutePath());
                graphMLW.save(graph, writer);
            } else {
                throw new Exception();
            }
        } catch (IOException iex) {
            iex.printStackTrace();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    class EdgeFactory implements Factory {

        String strEdge;
        int intIdEdge;
        
        public EdgeFactory(int id) {
            intIdEdge = id;
        }
        
        @Override
        public edge create() {

            strEdge = JOptionPane.showInputDialog("Digite os valores da aresta separados por ';'");
            edge e = new edge(intIdEdge);
            if (!strEdge.trim().isEmpty()) {
                e.setValue(strEdge);
                return e;
            } else {
                return null;
            }
        }
        
        public String getEdge() {
            return strEdge;
        }
    }

    class VertexFactory implements Factory<String> {

        @Override
        public String create() {


            String strVertex;

            if (graph.containsVertex("Inicio")) {
                strVertex = JOptionPane.showInputDialog("Digite o valor do vértice");
            } else {
                strVertex = "Inicio";
            }

            if (!strVertex.trim().isEmpty()) {
                return strVertex;
            } else {
                return null;
            }
        }
    }
}
